using System;
using System.Drawing;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

using GoblinXNA;
using GoblinXNA.Sounds;
using GoblinXNA.Graphics;
using GoblinXNA.SceneGraph;
using Model = GoblinXNA.Graphics.Model;
using Color = Microsoft.Xna.Framework.Color;
using GoblinXNA.UI.UI2D;
using GoblinXNA.Graphics.Geometry;
using GoblinXNA.Device.Capture;
using GoblinXNA.Device.Vision;
using GoblinXNA.Device.Vision.Marker;
using GoblinXNA.Device.Util;
using GoblinXNA.Device.Generic;
using GoblinXNA.Physics;
using GoblinXNA.Physics.Newton1;
using GoblinXNA.Helpers;
using GoblinXNA.Shaders;

namespace SplashOn
{

    public class Sample : Microsoft.Xna.Framework.Game
    {

        GraphicsDeviceManager graphics;
        Scene scene;
        bool useStaticImage = false;
        SpriteFont textFont;
        Vector2 textScale = new Vector2(0.4f, 0.4f);
        float startTextY = 80;
        float yTextHeight = 18;
        float xTesxtMinus; // see Initialize(), it is actually this --> xTesxtMinus = graphics.PreferredBackBufferWidth - 10;
        static string displayLabel = "";
        static string transformLabel = "";
        static string modelLabel = "";
        static string axisLabel = "";

        Sound sound = Sound.Instance;

        public Sample()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            graphics.PreferredBackBufferWidth = 800;
            graphics.PreferredBackBufferHeight = 600;


        }

        protected override void Initialize()
        {
            base.Initialize();
            State.InitGoblin(graphics, Content, "");

            scene = new Scene();

            scene.PhysicsEngine = new NewtonPhysics();
            //sound.Initialize("Tutorial9");
            //State.ThreadOption = (ushort)ThreadOptions.MarkerTracking;

            textFont = Content.Load<SpriteFont>("Sample");

            // Set up optical marker tracking
            // Note that we don't create our own camera when we use optical marker
            // tracking. It'll be created automatically
            SetupMarkerTracking();

            // Set up the lights used in the scene
            CreateLights();

            // Enable shadow mapping
            // NOTE: In order to use shadow mapping, you will need to add 'MultiLightShadowMap.fx'
            // and 'SimpleShadowShader.fx' shader files to your 'Content' directory. Also in here,
            // we're creating the ShadowMap before the creation of 3D objects since we need to assign
            // this ShadowMap to the IShadowShader used for the 3D objects
            //scene.ShadowMap = new MultiLightShadowMap();

            // Create 3D objects
            CreateObjects();

            // Create the ground that represents the physical ground marker array
            CreateGround();

            // Show Frames-Per-Second on the screen for debugging
            State.ShowFPS = false;
            State.ShowTriangleCount = false;
            State.ShowNotifications = false;
            displayLabel = "Initialization Done";
            xTesxtMinus = graphics.PreferredBackBufferWidth - 10;

            KeyboardInput.Instance.KeyPressEvent += new HandleKeyPress(KeyPressHandler);
        }

        private void SetupMarkerTracking()
        {
            IVideoCapture captureDevice = null;

            if (useStaticImage)
            {
                captureDevice = new NullCapture();
                captureDevice.InitVideoCapture(0, FrameRate._30Hz, Resolution._800x600,
                    ImageFormat.R8G8B8_24, false);
                ((NullCapture)captureDevice).StaticImageFile = "MarkerGround.gif";
            }
            else
            {
                // Create our video capture device that uses DirectShow library. Note that 
                // the combinations of resolution and frame rate that are allowed depend on 
                // the particular video capture device. Thus, setting incorrect resolution 
                // and frame rate values may cause exceptions or simply be ignored, depending 
                // on the device driver.  The values set here will work for a Microsoft VX 6000, 
                // and many other webcams.
                captureDevice = new DirectShowCapture2();
                captureDevice.InitVideoCapture(0, FrameRate._60Hz, Resolution._800x600,
                    ImageFormat.R8G8B8_24, false);
            }

            // Add this video capture device to the scene so that it can be used for
            // the marker tracker
            scene.AddVideoCaptureDevice(captureDevice);

            ALVARMarkerTracker tracker = new ALVARMarkerTracker();
            tracker.MaxMarkerError = 0.02f;
            tracker.InitTracker(captureDevice.Width, captureDevice.Height, "calib.xml", 32.4f);

            // Set the marker tracker to use for our scene
            scene.MarkerTracker = tracker;

            // Display the camera image in the background. Note that this parameter should
            // be set after adding at least one video capture device to the Scene class.            
            scene.ShowCameraImage = true;
        }

        private void CreateLights()
        {
            // Create a directional light source
            LightSource lightSource = new LightSource();
            lightSource.Direction = new Vector3(1, -1, -1);
            lightSource.Diffuse = Color.White.ToVector4();
            lightSource.Specular = new Vector4(0.6f, 0.6f, 0.6f, 1);

            // Create a light node to hold the light source
            LightNode lightNode = new LightNode();
            lightNode.LightSource = lightSource;

            // Set this light node to cast shadows (by just setting this to true will not cast any shadows,
            // scene.ShadowMap needs to be set to a valid IShadowMap and Model.Shader needs to be set to
            // a proper IShadowShader implementation
            lightNode.CastShadows = true;

            // You should also set the light projection when casting shadow from this light
            //lightNode.LightProjection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, 1, 1f, 500);

            scene.RootNode.AddChild(lightNode);
        }

        private void CreateObjects()
        {
            Console.WriteLine(" create objects ");
            ModelLoader modelLoader = new ModelLoader();
        }

        private void CreateGround()
        {
            GeometryNode groundNode = new GeometryNode("Ground");
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            Content.Unload();
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            scene.Update(gameTime.ElapsedGameTime, gameTime.IsRunningSlowly, this.IsActive);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {            
            scene.Draw(gameTime.ElapsedGameTime, gameTime.IsRunningSlowly);
        }

        private void KeyPressHandler(Keys keys, KeyModifier modifier)
        {            
            if(keys == Keys.Z) 
            {
                Console.WriteLine("Capturing scene");
                //scene.CaptureScene("samplescene");
                
                IntPtr img = new IntPtr();
                int[] imgAry = new int[graphics.PreferredBackBufferWidth * graphics.PreferredBackBufferHeight];
                scene.VideoCaptures.ToArray()[0].GetImageTexture(imgAry, ref img);
                Console.WriteLine(";;; " + imgAry.Length);             
                int midPoint = ((graphics.PreferredBackBufferHeight / 2) - 1) * graphics.PreferredBackBufferWidth + 
                    (graphics.PreferredBackBufferWidth / 2);
                Console.WriteLine("Finished capturing scene ");               
            }
            if (keys == (Keys.X))
            {
                Console.WriteLine("GetFullPath: " + System.IO.Path.GetFullPath("samplescene.jpg"));
                String s = System.IO.Path.GetFullPath("samplescene.jpg").Replace("\\", "\\\\");
                Console.WriteLine("GetFullPath::: " + s);                
                Bitmap image = new Bitmap(s);
                System.Drawing.Color c = image.GetPixel(40, 40);
                Console.WriteLine("color: " + c.ToString());
                //image.Dispose();
                //System.IO.File.Delete(System.IO.Path.GetFullPath("samplescene.jpg"));
            }
        }

    }

}
